package me.sdevil507.supports.global.handler;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import me.sdevil507.supports.helper.CommonRequestHelper;
import me.sdevil507.supports.result.ApiResultDTO;
import me.sdevil507.supports.result.ApiResultGenerator;
import me.sdevil507.supports.shiro.kickout.KickoutHandler;
import me.sdevil507.supports.status.ApiStatusCode;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;

/**
 * 支持Api与Web方式的踢出处理
 *
 * @author sdevil507
 * created on 2020/5/9
 */
@Slf4j
public class MultiKickoutHandler implements KickoutHandler {

    @SneakyThrows
    @Override
    public boolean exec(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, String loginUrl) {
        String token = httpServletRequest.getHeader("token");
        if (CommonRequestHelper.isAjax(httpServletRequest) || !StringUtils.isEmpty(token)) {
            // 如果是ajax请求
            ApiResultDTO apiResultDTO = ApiResultGenerator.create(ApiStatusCode.ACCOUNT_KICKEDOUT.getCode(), ApiStatusCode.ACCOUNT_KICKEDOUT.getDescription());
            respMsg(httpServletResponse, apiResultDTO);
            return false;
        } else {
            if (!httpServletRequest.getRequestURI().equals(loginUrl)) {
                // 如果是普通请求,跳转至登录页
                httpServletResponse.setCharacterEncoding("utf-8");
                httpServletResponse.setContentType("text/html;charset=utf-8;");
                httpServletResponse.getWriter()
                        .write("<script>window.alert(\"您的账号已经在其他地方登陆!\");window.parent.location.href='" + loginUrl + "'</script>");
                return false;
            } else {
                // 再次通过页面登录时需要清除kickout标签
                Session session = SecurityUtils.getSubject().getSession();
                session.removeAttribute("kickout");
                return true;
            }
        }
    }

    /**
     * 执行json返回
     *
     * @param response     响应
     * @param apiResultDTO 返回实体
     */
    private void respMsg(HttpServletResponse response, ApiResultDTO apiResultDTO) {
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
        response.setContentType("application/json; charset=utf-8");
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.addHeader("Access-Control-Allow-Methods", "*");
        response.setHeader("Access-Control-Allow-Headers", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        try (PrintWriter out = response.getWriter()) {
            ObjectMapper mapper = new ObjectMapper();
            out.append(mapper.writeValueAsString(apiResultDTO));
        } catch (IOException e) {
            log.error("IO异常:", e);
        }
    }

}
